package pt.inescid.components.policyengine.heimdall.pdp.base;

import java.lang.reflect.Method;
import java.util.Vector;

import pt.inescid.components.policyengine.heimdall.commons.Log;
import pt.inescid.components.policyengine.heimdall.pap.base.ExternalMethodDefinition;

public class ExternalMethodInstance extends SimpleInstance {

	private ExternalMethodDefinition definition = null;
	
//  ----------------------------------------------------------
//  ------------------------   constructor   ------------------------
//  ----------------------------------------------------------
	public ExternalMethodInstance(ExternalMethodDefinition definition,
			ModelInstance currentModel, 
			PolicyInstance currentPolicy) {
		super(definition, currentPolicy);
		this.definition = definition;
	}

	
	
	
//  ----------------------------------------------------------
//  ------------------------   evaluate   ------------------------
//  ----------------------------------------------------------
	public Object evaluate(ModelInstance currentModel, boolean onlyCached) {

		String completeName = definition.getValue();
		String className = null;
		String methodName = null;
		String methodParameters = null;
		Object returnValue = null;
		
		className = completeName.substring(0,
				completeName.substring(0, completeName.indexOf("(")).lastIndexOf("."));
		
		methodName = completeName.substring(
				completeName.substring(0, completeName.indexOf("(")).lastIndexOf(".")+1,
				completeName.indexOf("("));

		methodParameters = completeName.substring(
				completeName.indexOf("(")+1,
				completeName.indexOf(")"));
		
		Vector allParameters = new Vector();
		if (!methodParameters.equals("")) {
			while (methodParameters.contains(",")) {
				allParameters.add(methodParameters.substring(0,
						methodParameters.indexOf(",")));
				methodParameters = methodParameters.substring(
						methodParameters.indexOf(","));
			}
			
			allParameters.add(methodParameters);
		}
		
		try {
			Class externalClass = 
				Class.forName(className);
			
			Method[] allMethods = externalClass.getMethods();
			Method externalMethod = null; 
			for (int i = 0; i < allMethods.length; i++) {
				if (allMethods[i].getName().equals(
						methodName)) {
					
					externalMethod = allMethods[i];
					i = allMethods.length;
				}
			}
			
			Object argList[] = new Object[allParameters.size()];
			for (int i = 0; i < allParameters.size(); i++) {
				if (((String) allParameters.elementAt(i)).startsWith("ce.")) {
					argList[i] = currentModel.getCe();
				}
			}
			
			returnValue =  externalMethod.invoke(null, argList);
		}
		catch (Exception e) {
			Log.debug(Log.ERROR, "Error in invocation: " +
					e.getMessage() + "-" +
					e.getCause(), "ExternalMethodInstance.evaluate");
			return (null);
		}

		return (returnValue);
	} // evaluate

}; // ExternalMethodInstance
